
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    //图片上传相关属性，参考wx.uploadFile

    imageCloudPath: String,
    imageUploadHeader: Object,
    imageUploadFormData: Object,


 

    //输入内容
    nodes: Array,
    html: String,
    //内容输出格式，参考rich-text组件，默认为节点列表
    outputType: {
      type: String,
      value: 'html',
    },

  },

  /**
   * 组件的初始数据
   */
  data: {

    nodeList: [],
    textBufferPool: [],
    cindex: -1,
  },

  attached: function () {

    if (this.properties.nodes && this.properties.nodes.length > 0) {
      const textBufferPool = [];
      this.properties.nodes.forEach((node, index) => {
        if (node.name === 'p') {
          textBufferPool[index] = node.children[0].text;
        }
      })
      this.setData({
        textBufferPool,
        nodeList: this.properties.nodes,
      })
    } else if (this.properties.html) {
      this.setHtml(this.properties.html)
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 事件：添加文本
     */
    addText: function (e) {
      this.writeTextToNode();
      const index = e.currentTarget.dataset.index;
      // console.log(index)
      const node = {
        name: 'p',
        attrs: {
          class: 'xing-p',
        },
        children: [{
          type: 'text',
          text: ''
        }]
      }
      const nodeList = this.data.nodeList;
      const textBufferPool = this.data.textBufferPool;
      nodeList.splice(index + 1, 0, node);
      textBufferPool.splice(index + 1, 0, '');
      this.setData({
        nodeList,
        textBufferPool,
        cindex: nodeList.length
      })
      // console.log(this.data.cindex)
    },

    
    /**
     * 事件：添加图片
     */
    addImage: function (e) {
      this.writeTextToNode();
      const index = e.currentTarget.dataset.index;
      //   console.log(index)
      wx.chooseImage({
        // count: 1,
        success: res => {
          const tempFilePaths = res.tempFilePaths;
          for (let i = 0; i < tempFilePaths.length; i++) {
            const tempFilePath = res.tempFilePaths[i];
            wx.getImageInfo({
              src: tempFilePath,
              success: res => {
                const node = {
                  name: 'img',
                  attrs: {
                    class: 'xing-img',
                    style: 'width: 100%',
                    src: tempFilePath,                   
                    _uploaded: false,
                    _height: res.height / res.width,
                  },
                }     

                this.uploadImage(node).then((node) => {           
                  let nodeList = this.data.nodeList;
                  let textBufferPool = this.data.textBufferPool;
                  nodeList.push(node); // splice(index + 1, 0, node);
                  textBufferPool.push(tempFilePath); // splice(index + 1, 0, tempFilePath);
                  this.setData({
                    nodeList,
                    textBufferPool,
                    cindex: nodeList.length
                  })
                })
              }
            }) 
          }

         
        },
      })
    },
  
    /**
     * 事件：删除节点
     */
    deleteNode: function (e) {
      this.writeTextToNode();
      const index = e.currentTarget.dataset.index;
      let nodeList = this.data.nodeList;
      let textBufferPool = this.data.textBufferPool;
      nodeList.splice(index, 1);
      textBufferPool.splice(index, 1);
      this.setData({
        nodeList,
        textBufferPool,
        cindex: nodeList.length
      })
    },

    /**
     * 事件：上移
     */
    upNode: function (e) {
      this.writeTextToNode();
      const index = e.currentTarget.dataset.index;
      let nodeList = this.data.nodeList;
      this.swapArray(nodeList, index, index - 1);
      let textBufferPool = this.data.textBufferPool;
      this.swapArray(textBufferPool, index, index - 1);
      this.setData({
        nodeList,
        textBufferPool,
      })
    },

    /**
     * 事件：下移
     */
    downNode: function (e) {
      this.writeTextToNode();
      const index = e.currentTarget.dataset.index;
      let nodeList = this.data.nodeList;
      this.swapArray(nodeList, index, index + 1);
      let textBufferPool = this.data.textBufferPool;
      this.swapArray(textBufferPool, index, index + 1);
      this.setData({
        nodeList,
        textBufferPool,
      })
    },

    swapArray(arr, index1, index2) {
      arr[index1] = arr.splice(index2, 1, arr[index1])[0]
      return arr
    },

    /**
     * 事件：文本输入
     */
    onTextareaInput: function (e) {
      const index = e.currentTarget.dataset.index;
      let textBufferPool = this.data.textBufferPool;
      textBufferPool[index] = e.detail.value;
      this.setData({
        textBufferPool,
      })
    },

    /**
     * 事件：提交内容
     */
    onFinish: function (e) {   
      wx.showLoading({
        title: '正在保存',
      })
      this.writeTextToNode();
      this.handleOutput();   
    }, 
 

    /**
     * 方法：HTML转义
     */
    htmlEncode: function (str) {
      var s = "";
      if (str.length == 0) return "";
      s = str.replace(/&/g, "&gt;");
      s = s.replace(/</g, "&lt;");
      s = s.replace(/>/g, "&gt;");
      s = s.replace(/ /g, "&nbsp;");
      s = s.replace(/\'/g, "&#39;");
      s = s.replace(/\"/g, "&quot;");
      s = s.replace(/\n/g, "<br>");
      return s;
    },

    /**
     * 方法：HTML转义
     */
    htmlDecode: function (str) {
      var s = "";
      if (str.length == 0) return "";
      s = str.replace(/&gt;/g, "&");
      s = s.replace(/&lt;/g, "<");
      s = s.replace(/&gt;/g, ">");
      s = s.replace(/&nbsp;/g, " ");
      s = s.replace(/&#39;/g, "\'");
      s = s.replace(/&quot;/g, "\"");
      s = s.replace(/<br>/g, "\n");
      return s;
    },

    /**
     * 方法：将缓冲池的文本写入节点
     */
    writeTextToNode: function (e) {

      const textBufferPool = this.data.textBufferPool;
      const nodeList = this.data.nodeList;
      nodeList.forEach((node, index) => {
        if (node.name === 'p') {
          node.children[0].text = textBufferPool[index];
        }
      })
      this.setData({
        nodeList
      })
      return nodeList
    },

    getHtml() {
      this.handleOutput();
      var nodes = this.writeTextToNode();
      return this.nodeListToHTML(nodes);
    },

    getNodes() {
      this.handleOutput();
      return this.writeTextToNode();
    },

    setNodes(nodeList) {
      const textBufferPool = [];
      nodeList.forEach((node, index) => {
        if (node.name === 'p') {
          textBufferPool[index] = node.children[0].text;
        }
      })
      this.setData({
        textBufferPool,
        nodeList,
      })
    },

    setHtml(html) {
      if (!html.startsWith('<')) {
        html = '<p>' + html + '</p>';
      }
      const nodeList = this.HTMLtoNodeList(html);
      const textBufferPool = [];
      nodeList.forEach((node, index) => {
        if (node.name === 'p') {
          textBufferPool[index] = node.children[0].text;
        }
      })
      this.setData({
        textBufferPool,
        nodeList,
      })
    },

    /**
     * 方法：将HTML转为节点
     */
    HTMLtoNodeList: function (html) {
      //let html = this.properties.html;
      let htmlNodeList = [];
      while (html.length > 0) {
        const endTag = html.match(/<\/[a-z0-9]+>/);
        if (!endTag) break;
        const htmlNode = html.substring(0, endTag.index + endTag[0].length);
        htmlNodeList.push(htmlNode);
        html = html.substring(endTag.index + endTag[0].length);
      }
      return htmlNodeList.map(htmlNode => {
        let node = {
          attrs: {}
        };
        const startTag = htmlNode.match(/<[^<>]+>/);
        const startTagStr = startTag[0].substring(1, startTag[0].length - 1).trim();
        node.name = startTagStr.split(/\s+/)[0];
        const maps = startTagStr.match(/[^\s]+="[^"]+"/g);
        if (maps) {
          maps.forEach(attr => {
            const [name, value] = attr.split('=');
            node.attrs[name] = value.replace(/"/g, '');
          })
        }
        if (node.name === 'p') {
          const endTag = htmlNode.match(/<\/[a-z0-9]+>/);
          const text = this.htmlDecode(htmlNode.substring(startTag.index + startTag[0].length, endTag.index).trim());
          node.children = [{
            text,
            type: 'text',
          }]
        }
        return node;
      })
    },

    /**
     * 方法：将节点转为HTML
     */
    nodeListToHTML: function (nodeList) {
      return nodeList.map(node => `<${node.name} ${Object.keys(node.attrs).map(key => `${key}="${node.attrs[key]}"`).join(' ')}>${node.children ? this.htmlEncode(node.children[0].text) : ''}</${node.name}>`).join('');
    },

    /**
     * 方法：上传图片
     */
    uploadImage: function (node) {
      return new Promise(resolve => {
        wx.showLoading({
          title: '正在上传图片',
        })
     
        let fn = Math.random().toString(36).substr(2) + node.attrs.src.match(/\.[^.]+?$/)[0];
        let options = {
          filePath: node.attrs.src,
          cloudPath: this.properties.imageCloudPath + fn       
        }
        if (this.properties.imageUploadHeader) {
          options.header = this.properties.imageUploadHeader;
        }
        if (this.properties.imageUploadFormData) {
          options.formData = this.properties.imageUploadFormData;
        }
        options.success = res => {
          console.log(res);
          const url = res.fileID;
        
          console.log(url);
          node.attrs.src = url;
          node.attrs._uploaded = true;
          resolve(node);
          wx.hideLoading();
        }
        options.fail = err => {
          console.error(err);
          wx.hideLoading();
          wx.showToast({ title: '上传失败', icon: 'none' })
        }
        wx.cloud.uploadFile(options);

      })
    },

    /**
     * 方法：处理节点，递归
     */
    handleOutput: function (index = 0) {
      let nodeList = this.data.nodeList;
      if (index >= nodeList.length) {
        wx.hideLoading();
        if (this.properties.outputType.toLowerCase() === 'array') {
          this.triggerEvent('finish', {
            content: this.data.nodeList
          });
        }
        if (this.properties.outputType.toLowerCase() === 'html') {
          this.triggerEvent('finish', {
            content: this.nodeListToHTML(this.data.nodeList)
          });
        }
       
        return;
      }
      const node = nodeList[index];
      if (node.name === 'img' && !node.attrs._uploaded) {
        this.uploadImage(node).then(() => {         
          this.handleOutput(index + 1)
        });
      } else {
        this.handleOutput(index + 1);
      }
    },
  }
})